﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.Encounters;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.Core;
using TaleWorlds.Library;
using TaleWorlds.SaveSystem;

namespace TaleWorlds.CampaignSystem.Roster
{
	// Token: 0x0200028A RID: 650
	public class TroopRoster : ISerializableObject
	{
		// Token: 0x06002309 RID: 8969 RVA: 0x00094E3C File Offset: 0x0009303C
		internal static void AutoGeneratedStaticCollectObjectsTroopRoster(object o, List<object> collectedObjects)
		{
			((TroopRoster)o).AutoGeneratedInstanceCollectObjects(collectedObjects);
		}

		// Token: 0x0600230A RID: 8970 RVA: 0x00094E4A File Offset: 0x0009304A
		protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
		{
			collectedObjects.Add(this.data);
			collectedObjects.Add(this.OwnerParty);
		}

		// Token: 0x0600230B RID: 8971 RVA: 0x00094E64 File Offset: 0x00093064
		internal static object AutoGeneratedGetMemberValueOwnerParty(object o)
		{
			return ((TroopRoster)o).OwnerParty;
		}

		// Token: 0x0600230C RID: 8972 RVA: 0x00094E71 File Offset: 0x00093071
		internal static object AutoGeneratedGetMemberValuedata(object o)
		{
			return ((TroopRoster)o).data;
		}

		// Token: 0x0600230D RID: 8973 RVA: 0x00094E7E File Offset: 0x0009307E
		internal static object AutoGeneratedGetMemberValue_count(object o)
		{
			return ((TroopRoster)o)._count;
		}

		// Token: 0x0600230E RID: 8974 RVA: 0x00094E90 File Offset: 0x00093090
		internal static object AutoGeneratedGetMemberValue_isPrisonRoster(object o)
		{
			return ((TroopRoster)o)._isPrisonRoster;
		}

		// Token: 0x170008C6 RID: 2246
		// (get) Token: 0x0600230F RID: 8975 RVA: 0x00094EA2 File Offset: 0x000930A2
		// (set) Token: 0x06002310 RID: 8976 RVA: 0x00094EAA File Offset: 0x000930AA
		[CachedData]
		internal NumberChangedCallback NumberChangedCallback { get; set; }

		// Token: 0x170008C7 RID: 2247
		// (get) Token: 0x06002311 RID: 8977 RVA: 0x00094EB3 File Offset: 0x000930B3
		// (set) Token: 0x06002312 RID: 8978 RVA: 0x00094EBB File Offset: 0x000930BB
		[SaveableProperty(2)]
		internal PartyBase OwnerParty { get; private set; }

		// Token: 0x170008C8 RID: 2248
		// (get) Token: 0x06002313 RID: 8979 RVA: 0x00094EC4 File Offset: 0x000930C4
		public int Count
		{
			get
			{
				return this._count;
			}
		}

		// Token: 0x170008C9 RID: 2249
		// (get) Token: 0x06002314 RID: 8980 RVA: 0x00094ECC File Offset: 0x000930CC
		// (set) Token: 0x06002315 RID: 8981 RVA: 0x00094ED4 File Offset: 0x000930D4
		[CachedData]
		public int VersionNo { get; private set; }

		// Token: 0x170008CA RID: 2250
		// (get) Token: 0x06002316 RID: 8982 RVA: 0x00094EDD File Offset: 0x000930DD
		public int TotalRegulars
		{
			get
			{
				return this._totalRegulars;
			}
		}

		// Token: 0x170008CB RID: 2251
		// (get) Token: 0x06002317 RID: 8983 RVA: 0x00094EE5 File Offset: 0x000930E5
		public int TotalWoundedRegulars
		{
			get
			{
				return this._totalWoundedRegulars;
			}
		}

		// Token: 0x170008CC RID: 2252
		// (get) Token: 0x06002318 RID: 8984 RVA: 0x00094EED File Offset: 0x000930ED
		public int TotalWoundedHeroes
		{
			get
			{
				return this._totalWoundedHeroes;
			}
		}

		// Token: 0x170008CD RID: 2253
		// (get) Token: 0x06002319 RID: 8985 RVA: 0x00094EF5 File Offset: 0x000930F5
		public int TotalHeroes
		{
			get
			{
				return this._totalHeroes;
			}
		}

		// Token: 0x170008CE RID: 2254
		// (get) Token: 0x0600231A RID: 8986 RVA: 0x00094EFD File Offset: 0x000930FD
		public int TotalWounded
		{
			get
			{
				return this._totalWoundedRegulars + this._totalWoundedHeroes;
			}
		}

		// Token: 0x170008CF RID: 2255
		// (get) Token: 0x0600231B RID: 8987 RVA: 0x00094F0C File Offset: 0x0009310C
		public int TotalManCount
		{
			get
			{
				return this._totalRegulars + this._totalHeroes;
			}
		}

		// Token: 0x170008D0 RID: 2256
		// (get) Token: 0x0600231C RID: 8988 RVA: 0x00094F1B File Offset: 0x0009311B
		public int TotalHealthyCount
		{
			get
			{
				return this._totalRegulars + this._totalHeroes - (this._totalWoundedRegulars + this._totalWoundedHeroes);
			}
		}

		// Token: 0x170008D1 RID: 2257
		// (get) Token: 0x0600231D RID: 8989 RVA: 0x00094F38 File Offset: 0x00093138
		// (set) Token: 0x0600231E RID: 8990 RVA: 0x00094F40 File Offset: 0x00093140
		public bool IsPrisonRoster
		{
			get
			{
				return this._isPrisonRoster;
			}
			set
			{
				this._isPrisonRoster = value;
			}
		}

		// Token: 0x0600231F RID: 8991 RVA: 0x00094F49 File Offset: 0x00093149
		public TroopRoster(PartyBase ownerParty) : this()
		{
			this.OwnerParty = ownerParty;
		}

		// Token: 0x06002320 RID: 8992 RVA: 0x00094F58 File Offset: 0x00093158
		private TroopRoster()
		{
			this.data = new TroopRosterElement[4];
			this._count = 0;
			this._troopRosterElements = new MBList<TroopRosterElement>();
			this.InitializeCachedData();
		}

		// Token: 0x06002321 RID: 8993 RVA: 0x00094F84 File Offset: 0x00093184
		public static TroopRoster CreateDummyTroopRoster()
		{
			return new TroopRoster();
		}

		// Token: 0x06002322 RID: 8994 RVA: 0x00094F8B File Offset: 0x0009318B
		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		// Token: 0x06002323 RID: 8995 RVA: 0x00094F93 File Offset: 0x00093193
		[LoadInitializationCallback]
		private void OnLoad(MetaData metaData)
		{
			this._troopRosterElementsVersion = -1;
			this._troopRosterElements = new MBList<TroopRosterElement>();
			TroopRoster.InstanceListForLoadGame.Add(this);
		}

		// Token: 0x06002324 RID: 8996 RVA: 0x00094FB4 File Offset: 0x000931B4
		private void EnsureLength(int length)
		{
			if (length > 0 && (this.data == null || length > this.data.Length))
			{
				int num = 4;
				if (this.data != null)
				{
					num = this.data.Length * 2;
				}
				TroopRosterElement[] array = new TroopRosterElement[num];
				for (int i = 0; i < this._count; i++)
				{
					array[i] = this.data[i];
				}
				this.data = array;
			}
		}

		// Token: 0x06002325 RID: 8997 RVA: 0x00095020 File Offset: 0x00093220
		public static void CalculateCachedStatsOnLoad()
		{
			foreach (TroopRoster troopRoster in TroopRoster.InstanceListForLoadGame)
			{
				troopRoster.InitializeCachedData();
			}
			TroopRoster.InstanceListForLoadGame.Clear();
		}

		// Token: 0x06002326 RID: 8998 RVA: 0x0009507C File Offset: 0x0009327C
		private void InitializeCachedData()
		{
			this._isInitialized = true;
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			for (int i = 0; i < this._count; i++)
			{
				TroopRosterElement troopRosterElement = this.data[i];
				if (troopRosterElement.Character.IsHero)
				{
					num++;
					if (troopRosterElement.Character.HeroObject.IsWounded)
					{
						num2++;
					}
				}
				else
				{
					num3 += this.data[i].Number;
					num4 += this.data[i].WoundedNumber;
				}
			}
			this._totalWoundedHeroes = num2;
			this._totalWoundedRegulars = num4;
			this._totalHeroes = num;
			this._totalRegulars = num3;
		}

		// Token: 0x06002327 RID: 8999 RVA: 0x0009512D File Offset: 0x0009332D
		public FlattenedTroopRoster ToFlattenedRoster()
		{
			return new FlattenedTroopRoster(this.TotalManCount)
			{
				this.GetTroopRoster()
			};
		}

		// Token: 0x06002328 RID: 9000 RVA: 0x00095148 File Offset: 0x00093348
		public void Add(IEnumerable<FlattenedTroopRosterElement> elementList)
		{
			foreach (FlattenedTroopRosterElement flattenedTroopRosterElement in elementList)
			{
				this.AddToCounts(flattenedTroopRosterElement.Troop, 1, false, flattenedTroopRosterElement.IsWounded ? 1 : 0, flattenedTroopRosterElement.Xp, true, -1);
			}
		}

		// Token: 0x06002329 RID: 9001 RVA: 0x000951B0 File Offset: 0x000933B0
		public void Add(TroopRoster troopRoster)
		{
			foreach (TroopRosterElement troopRosterElement in troopRoster.GetTroopRoster())
			{
				this.Add(troopRosterElement);
			}
		}

		// Token: 0x0600232A RID: 9002 RVA: 0x00095204 File Offset: 0x00093404
		public void Add(TroopRosterElement troopRosterElement)
		{
			this.AddToCounts(troopRosterElement.Character, troopRosterElement.Number, false, troopRosterElement.WoundedNumber, troopRosterElement.Xp, true, -1);
		}

		// Token: 0x0600232B RID: 9003 RVA: 0x0009522C File Offset: 0x0009342C
		public ICollection<TroopRosterElement> RemoveIf(Predicate<TroopRosterElement> match)
		{
			List<TroopRosterElement> list = new List<TroopRosterElement>();
			bool flag = false;
			for (int i = 0; i < this._count; i++)
			{
				if (match(this.data[i]))
				{
					TroopRosterElement elementCopyAtIndex = this.GetElementCopyAtIndex(i);
					list.Add(elementCopyAtIndex);
					this.AddToCountsAtIndex(i, -elementCopyAtIndex.Number, -elementCopyAtIndex.WoundedNumber, -elementCopyAtIndex.Xp, true);
					i--;
					flag = true;
				}
			}
			if (flag)
			{
				this.UpdateVersion();
			}
			return list;
		}

		// Token: 0x0600232C RID: 9004 RVA: 0x000952A8 File Offset: 0x000934A8
		public int FindIndexOfTroop(CharacterObject character)
		{
			for (int i = 0; i < this._count; i++)
			{
				if (this.data[i].Character == character)
				{
					return i;
				}
			}
			return -1;
		}

		// Token: 0x0600232D RID: 9005 RVA: 0x000952E0 File Offset: 0x000934E0
		public CharacterObject GetManAtIndexFromFlattenedRosterWithFilter(int indexOfTroop, bool includeHeroes = false, bool countOnlyHealthyOnes = false)
		{
			for (int i = 0; i < this._count; i++)
			{
				if (includeHeroes || !this.data[i].Character.IsHero)
				{
					indexOfTroop -= (countOnlyHealthyOnes ? (this.data[i].Number - this.data[i].WoundedNumber) : this.data[i].Number);
					if (indexOfTroop < 0)
					{
						return this.data[i].Character;
					}
				}
			}
			return null;
		}

		// Token: 0x0600232E RID: 9006 RVA: 0x00095370 File Offset: 0x00093570
		private bool KillOneNonHeroTroopRandomly()
		{
			CharacterObject characterObject = null;
			int num = this._totalRegulars - this._totalWoundedRegulars;
			bool flag = num > 0;
			while (flag)
			{
				int indexOfTroop = MBRandom.RandomInt(num);
				characterObject = this.GetManAtIndexFromFlattenedRosterWithFilter(indexOfTroop, false, true);
				flag = (characterObject == null);
			}
			if (characterObject != null)
			{
				this.AddToCounts(characterObject, -1, false, 0, 0, true, -1);
				return true;
			}
			return false;
		}

		// Token: 0x0600232F RID: 9007 RVA: 0x000953C4 File Offset: 0x000935C4
		public void KillNumberOfNonHeroTroopsRandomly(int numberOfMen)
		{
			bool flag = true;
			int num = 0;
			while (num < numberOfMen && flag)
			{
				flag = this.KillOneNonHeroTroopRandomly();
				num++;
			}
		}

		// Token: 0x06002330 RID: 9008 RVA: 0x000953EC File Offset: 0x000935EC
		public void WoundNumberOfTroopsRandomly(int numberOfMen)
		{
			for (int i = 0; i < numberOfMen; i++)
			{
				CharacterObject characterObject = null;
				int num = this._totalRegulars - this._totalWoundedRegulars;
				bool flag = num > 0;
				while (flag)
				{
					flag = false;
					int indexOfTroop = MBRandom.RandomInt(num);
					characterObject = this.GetManAtIndexFromFlattenedRosterWithFilter(indexOfTroop, true, false);
					if (characterObject == null || characterObject.IsHero)
					{
						flag = true;
					}
				}
				if (characterObject != null)
				{
					this.WoundTroop(characterObject, 1, default(UniqueTroopDescriptor));
				}
			}
		}

		// Token: 0x06002331 RID: 9009 RVA: 0x00095458 File Offset: 0x00093658
		public void SwapTroopsAtIndices(int firstIndex, int secondIndex)
		{
			if (firstIndex < 0 || firstIndex >= this.Count || secondIndex < 0 || secondIndex >= this.Count)
			{
				Debug.FailedAssert("Troop roster swap indices are out of bounds.", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Roster\\TroopRoster.cs", "SwapTroopsAtIndices", 395);
				return;
			}
			if (firstIndex == secondIndex)
			{
				return;
			}
			TroopRosterElement troopRosterElement = this.data[firstIndex];
			this.data[firstIndex] = this.data[secondIndex];
			this.data[secondIndex] = troopRosterElement;
		}

		// Token: 0x06002332 RID: 9010 RVA: 0x000954D0 File Offset: 0x000936D0
		public void ShiftTroopToIndex(int troopIndex, int targetIndex)
		{
			if (troopIndex < 0 || troopIndex >= this.Count || targetIndex < 0 || targetIndex >= this.Count)
			{
				Debug.FailedAssert("Troop roster swap indices are out of bounds.", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Roster\\TroopRoster.cs", "ShiftTroopToIndex", 413);
				return;
			}
			if (troopIndex == targetIndex)
			{
				return;
			}
			int num = (troopIndex < targetIndex) ? 1 : -1;
			TroopRosterElement troopRosterElement = this.data[troopIndex];
			for (int num2 = troopIndex; num2 != targetIndex; num2 += num)
			{
				this.data[num2] = this.data[num2 + num];
			}
			this.data[targetIndex] = troopRosterElement;
		}

		// Token: 0x06002333 RID: 9011 RVA: 0x00095560 File Offset: 0x00093760
		public int AddToCountsAtIndex(int index, int countChange, int woundedCountChange = 0, int xpChange = 0, bool removeDepleted = true)
		{
			this.UpdateVersion();
			bool heroCountChanged = false;
			CharacterObject character = this.data[index].Character;
			bool isHero = character.IsHero;
			TroopRosterElement[] array = this.data;
			int num = index;
			array[num].Number = array[num].Number + countChange;
			int num2 = this.data[index].WoundedNumber + woundedCountChange;
			if (num2 > this.data[index].Number)
			{
				woundedCountChange += this.data[index].Number - num2;
			}
			else if (num2 < 0)
			{
				Debug.FailedAssert("false", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Roster\\TroopRoster.cs", "AddToCountsAtIndex", 455);
			}
			TroopRosterElement[] array2 = this.data;
			int num3 = index;
			array2[num3].WoundedNumber = array2[num3].WoundedNumber + woundedCountChange;
			if (xpChange != 0)
			{
				TroopRosterElement[] array3 = this.data;
				int num4 = index;
				array3[num4].Xp = array3[num4].Xp + xpChange;
			}
			if (this.IsPrisonRoster)
			{
				this.ClampConformity(index);
			}
			else
			{
				this.ClampXp(index);
			}
			if (isHero)
			{
				this._totalHeroes += countChange;
				if (character.HeroObject.IsWounded)
				{
					this._totalWoundedHeroes += countChange;
				}
				if (countChange != 0)
				{
					heroCountChanged = true;
				}
			}
			else
			{
				this._totalWoundedRegulars += woundedCountChange;
				this._totalRegulars += countChange;
			}
			if (removeDepleted && this.data[index].Number == 0)
			{
				this.RemoveRange(index, index + 1);
				index = -1;
			}
			if (this.OwnerParty != null && isHero)
			{
				if (countChange > 0)
				{
					if (!this.IsPrisonRoster)
					{
						this.OwnerParty.OnHeroAdded(character.HeroObject);
					}
					else
					{
						this.OwnerParty.OnHeroAddedAsPrisoner(character.HeroObject);
					}
				}
				else if (countChange < 0)
				{
					if (!this.IsPrisonRoster)
					{
						this.OwnerParty.OnHeroRemoved(character.HeroObject);
					}
					else
					{
						this.OwnerParty.OnHeroRemovedAsPrisoner(character.HeroObject);
					}
				}
			}
			if (countChange != 0 || woundedCountChange != 0)
			{
				this.OnNumberChanged(countChange != 0, woundedCountChange != 0, heroCountChanged);
			}
			return index;
		}

		// Token: 0x06002334 RID: 9012 RVA: 0x00095754 File Offset: 0x00093954
		private void RemoveRange(int p, int p2)
		{
			int num = p2 - p;
			for (int i = p2; i < this._count; i++)
			{
				this.data[i - num] = this.data[i];
			}
			for (int j = this._count - num; j < this._count; j++)
			{
				this.data[j].Clear();
			}
			this.UpdateVersion();
			this._count -= num;
		}

		// Token: 0x06002335 RID: 9013 RVA: 0x000957D0 File Offset: 0x000939D0
		private int AddNewElement(CharacterObject character, bool insertAtFront = false, int insertionIndex = -1)
		{
			int num = this._count + 1;
			this.EnsureLength(num);
			int num2 = (insertionIndex == -1) ? this._count : insertionIndex;
			if (insertAtFront)
			{
				num2 = 0;
			}
			if (this._count > num2)
			{
				for (int i = this._count; i > num2; i--)
				{
					this.data[i] = this.data[i - 1];
				}
			}
			this.data[num2] = new TroopRosterElement(character);
			this._count = num;
			this.UpdateVersion();
			return num2;
		}

		// Token: 0x06002336 RID: 9014 RVA: 0x00095854 File Offset: 0x00093A54
		[Conditional("DEBUG_MORE")]
		public void CheckValidity()
		{
			if (this.data == null)
			{
				return;
			}
			int num = 0;
			for (int i = 0; i < this.data.Length; i++)
			{
				TroopRosterElement troopRosterElement = this.data[i];
				if (troopRosterElement.Character != null)
				{
					int number = troopRosterElement.Number;
					int woundedNumber = troopRosterElement.WoundedNumber;
					num++;
				}
			}
		}

		// Token: 0x06002337 RID: 9015 RVA: 0x000958A8 File Offset: 0x00093AA8
		private void OnNumberChanged(bool numberChanged, bool woundedNumberChanged, bool heroCountChanged)
		{
			NumberChangedCallback numberChangedCallback = this.NumberChangedCallback;
			if (numberChangedCallback == null)
			{
				return;
			}
			numberChangedCallback(numberChanged, woundedNumberChanged, heroCountChanged);
		}

		// Token: 0x06002338 RID: 9016 RVA: 0x000958C0 File Offset: 0x00093AC0
		public int AddToCounts(CharacterObject character, int count, bool insertAtFront = false, int woundedCount = 0, int xpChange = 0, bool removeDepleted = true, int index = -1)
		{
			int num = this.FindIndexOfTroop(character);
			if (num < 0)
			{
				if (index >= 0)
				{
					if (count + woundedCount <= 0)
					{
						Debug.FailedAssert("false", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Roster\\TroopRoster.cs", "AddToCounts", 630);
						return -1;
					}
					num = this.AddNewElement(character, insertAtFront, index);
				}
				else
				{
					if (count + woundedCount <= 0)
					{
						return -1;
					}
					num = this.AddNewElement(character, insertAtFront, -1);
				}
			}
			if (this.AddToCountsAtIndex(num, count, woundedCount, xpChange, removeDepleted) != -1)
			{
				return num;
			}
			return -1;
		}

		// Token: 0x06002339 RID: 9017 RVA: 0x00095934 File Offset: 0x00093B34
		public int GetTroopCount(CharacterObject troop)
		{
			int num = this.FindIndexOfTroop(troop);
			if (num >= 0)
			{
				return this.data[num].Number;
			}
			return 0;
		}

		// Token: 0x0600233A RID: 9018 RVA: 0x00095960 File Offset: 0x00093B60
		public void RemoveZeroCounts()
		{
			int num = 0;
			for (int i = 0; i < this._count; i++)
			{
				if (this.data[i].Number > 0)
				{
					if (num != i)
					{
						this.data[num] = this.data[i];
					}
					num++;
				}
			}
			for (int j = num; j < this._count; j++)
			{
				this.data[j].Clear();
			}
			this._count = num;
			this.UpdateVersion();
		}

		// Token: 0x0600233B RID: 9019 RVA: 0x000959E3 File Offset: 0x00093BE3
		public TroopRosterElement GetElementCopyAtIndex(int index)
		{
			return this.data[index];
		}

		// Token: 0x0600233C RID: 9020 RVA: 0x000959F1 File Offset: 0x00093BF1
		public void SetElementNumber(int index, int number)
		{
			if (index < this._count)
			{
				this.data[index].Number = number;
				this.UpdateVersion();
				return;
			}
			throw new IndexOutOfRangeException();
		}

		// Token: 0x0600233D RID: 9021 RVA: 0x00095A1A File Offset: 0x00093C1A
		public int GetElementNumber(int index)
		{
			if (index >= 0 && index < this._count)
			{
				return this.data[index].Number;
			}
			return 0;
		}

		// Token: 0x0600233E RID: 9022 RVA: 0x00095A3C File Offset: 0x00093C3C
		public int GetElementNumber(CharacterObject character)
		{
			return this.GetElementNumber(this.FindIndexOfTroop(character));
		}

		// Token: 0x0600233F RID: 9023 RVA: 0x00095A4B File Offset: 0x00093C4B
		public void SetElementWoundedNumber(int index, int number)
		{
			if (index < this._count)
			{
				this.data[index].WoundedNumber = number;
				this.UpdateVersion();
				return;
			}
			throw new IndexOutOfRangeException();
		}

		// Token: 0x06002340 RID: 9024 RVA: 0x00095A74 File Offset: 0x00093C74
		public int GetElementWoundedNumber(int index)
		{
			if (index < this._count)
			{
				return this.data[index].WoundedNumber;
			}
			throw new IndexOutOfRangeException();
		}

		// Token: 0x06002341 RID: 9025 RVA: 0x00095A96 File Offset: 0x00093C96
		public void SetElementXp(int index, int number)
		{
			if (index < this._count)
			{
				this.data[index].Xp = number;
				this.UpdateVersion();
				return;
			}
			throw new IndexOutOfRangeException();
		}

		// Token: 0x06002342 RID: 9026 RVA: 0x00095ABF File Offset: 0x00093CBF
		public int GetElementXp(int index)
		{
			if (index < this._count && index >= 0)
			{
				return this.data[index].Xp;
			}
			return 0;
		}

		// Token: 0x06002343 RID: 9027 RVA: 0x00095AE1 File Offset: 0x00093CE1
		public int GetElementXp(CharacterObject character)
		{
			return this.GetElementXp(this.FindIndexOfTroop(character));
		}

		// Token: 0x06002344 RID: 9028 RVA: 0x00095AF0 File Offset: 0x00093CF0
		public CharacterObject GetCharacterAtIndex(int index)
		{
			if (index < this._count)
			{
				return this.data[index].Character;
			}
			throw new IndexOutOfRangeException();
		}

		// Token: 0x06002345 RID: 9029 RVA: 0x00095B14 File Offset: 0x00093D14
		public void FillMembersOfRoster(int neededNumber, CharacterObject basicTroop = null)
		{
			int num3;
			for (int num = (from element in this.GetTroopRoster()
			where !element.Character.IsHero
			select element).Sum((TroopRosterElement element) => element.Number); num != neededNumber; num += num3)
			{
				float num2 = MBRandom.RandomFloat * (float)num;
				CharacterObject character = basicTroop;
				foreach (TroopRosterElement troopRosterElement in from element in this.GetTroopRoster()
				where !element.Character.IsHero
				select element)
				{
					num2 -= (float)troopRosterElement.Number;
					if (num2 < 0f)
					{
						character = troopRosterElement.Character;
						break;
					}
				}
				num3 = ((num > neededNumber) ? -1 : 1);
				this.AddToCounts(character, num3, false, 0, 0, true, -1);
			}
		}

		// Token: 0x06002346 RID: 9030 RVA: 0x00095C24 File Offset: 0x00093E24
		public void WoundMembersOfRoster(float woundedRatio)
		{
			for (int i = 0; i < this.data.Length; i++)
			{
				TroopRosterElement troopRosterElement = this.data[i];
				if (troopRosterElement.Character != null)
				{
					if (troopRosterElement.Character.IsHero && MBRandom.RandomFloat < woundedRatio)
					{
						this.data[i].Character.HeroObject.MakeWounded(null, KillCharacterAction.KillCharacterActionDetail.None);
					}
					else
					{
						int woundedCount = (int)((float)troopRosterElement.Number * woundedRatio);
						this.AddToCounts(this.data[i].Character, 0, false, woundedCount, 0, true, -1);
					}
				}
			}
		}

		// Token: 0x06002347 RID: 9031 RVA: 0x00095CBA File Offset: 0x00093EBA
		public void Reset()
		{
			this.Clear();
			this.UpdateVersion();
		}

		// Token: 0x06002348 RID: 9032 RVA: 0x00095CC8 File Offset: 0x00093EC8
		public override bool Equals(object obj)
		{
			return this == obj;
		}

		// Token: 0x06002349 RID: 9033 RVA: 0x00095CD0 File Offset: 0x00093ED0
		public static bool operator ==(TroopRoster a, TroopRoster b)
		{
			if (a == b)
			{
				return true;
			}
			if (a == null || b == null)
			{
				return false;
			}
			if (a.Count != b.Count)
			{
				return false;
			}
			for (int i = 0; i < a.Count; i++)
			{
				TroopRosterElement elementCopyAtIndex = a.GetElementCopyAtIndex(i);
				int num = b.FindIndexOfTroop(elementCopyAtIndex.Character);
				if (num == -1)
				{
					return false;
				}
				TroopRosterElement elementCopyAtIndex2 = b.GetElementCopyAtIndex(num);
				if (elementCopyAtIndex.Character != elementCopyAtIndex2.Character || elementCopyAtIndex.Number != elementCopyAtIndex2.Number)
				{
					return false;
				}
			}
			return true;
		}

		// Token: 0x0600234A RID: 9034 RVA: 0x00095D50 File Offset: 0x00093F50
		public static bool operator !=(TroopRoster a, TroopRoster b)
		{
			return !(a == b);
		}

		// Token: 0x0600234B RID: 9035 RVA: 0x00095D5C File Offset: 0x00093F5C
		public bool Contains(CharacterObject character)
		{
			for (int i = 0; i < this.Count; i++)
			{
				TroopRosterElement elementCopyAtIndex = this.GetElementCopyAtIndex(i);
				if (character == elementCopyAtIndex.Character)
				{
					return true;
				}
			}
			return false;
		}

		// Token: 0x0600234C RID: 9036 RVA: 0x00095D90 File Offset: 0x00093F90
		public void ValidateTroopListCache()
		{
			if (this._troopRosterElementsVersion != this.VersionNo)
			{
				lock (this)
				{
					if (this._troopRosterElementsVersion != this.VersionNo)
					{
						this._troopRosterElements.Clear();
						this._troopRosterElements.Capacity = Math.Max(this._troopRosterElements.Capacity, this.Count);
						for (int i = 0; i < this.Count; i++)
						{
							this._troopRosterElements.Add(this.GetElementCopyAtIndex(i));
						}
						this._troopRosterElementsVersion = this.VersionNo;
					}
				}
			}
		}

		// Token: 0x0600234D RID: 9037 RVA: 0x00095E40 File Offset: 0x00094040
		public MBList<TroopRosterElement> GetTroopRoster()
		{
			this.ValidateTroopListCache();
			return this._troopRosterElements;
		}

		// Token: 0x0600234E RID: 9038 RVA: 0x00095E50 File Offset: 0x00094050
		public void Clear()
		{
			for (int i = this._count - 1; i >= 0; i--)
			{
				this.AddToCountsAtIndex(i, -this.data[i].Number, -this.data[i].WoundedNumber, 0, true);
			}
			this.UpdateVersion();
		}

		// Token: 0x0600234F RID: 9039 RVA: 0x00095EA4 File Offset: 0x000940A4
		private void ClampConformity(int index)
		{
			CharacterObject character = this.data[index].Character;
			if (!character.IsHero)
			{
				int maxValue = this.data[index].Number * character.ConformityNeededToRecruitPrisoner;
				int xp = this.data[index].Xp;
				this.data[index].Xp = MBMath.ClampInt(xp, 0, maxValue);
				return;
			}
			this.data[index].Xp = MathF.Max(this.data[index].Xp, 0);
		}

		// Token: 0x06002350 RID: 9040 RVA: 0x00095F38 File Offset: 0x00094138
		private void ClampXp(int index)
		{
			CharacterObject character = this.data[index].Character;
			if (!character.IsHero)
			{
				int num = 0;
				for (int i = 0; i < character.UpgradeTargets.Length; i++)
				{
					int upgradeXpCost = character.GetUpgradeXpCost(this.OwnerParty, i);
					if (num < upgradeXpCost)
					{
						num = upgradeXpCost;
					}
				}
				int xp = MBMath.ClampInt(this.data[index].Xp, 0, this.data[index].Number * num);
				this.data[index].Xp = xp;
				return;
			}
			this.data[index].Xp = MathF.Max(this.data[index].Xp, 0);
		}

		// Token: 0x06002351 RID: 9041 RVA: 0x00095FF4 File Offset: 0x000941F4
		public int AddXpToTroop(int xpAmount, CharacterObject attackerTroop)
		{
			int num = this.FindIndexOfTroop(attackerTroop);
			if (num >= 0)
			{
				return this.AddXpToTroopAtIndex(xpAmount, num);
			}
			return 0;
		}

		// Token: 0x06002352 RID: 9042 RVA: 0x00096018 File Offset: 0x00094218
		public int AddXpToTroopAtIndex(int xpAmount, int index)
		{
			int xp = this.data[index].Xp;
			TroopRosterElement[] array = this.data;
			array[index].Xp = array[index].Xp + xpAmount;
			if (this.IsPrisonRoster)
			{
				this.ClampConformity(index);
			}
			else
			{
				this.ClampXp(index);
			}
			return this.data[index].Xp - xp;
		}

		// Token: 0x06002353 RID: 9043 RVA: 0x0009607C File Offset: 0x0009427C
		public void RemoveTroop(CharacterObject troop, int numberToRemove = 1, UniqueTroopDescriptor troopSeed = default(UniqueTroopDescriptor), int xp = 0)
		{
			int index = this.FindIndexOfTroop(troop);
			bool removeDepleted = true;
			if (PlayerEncounter.CurrentBattleSimulation != null && !troop.IsHero)
			{
				removeDepleted = false;
			}
			this.AddToCountsAtIndex(index, -numberToRemove, 0, troop.IsHero ? 0 : (-xp), removeDepleted);
		}

		// Token: 0x06002354 RID: 9044 RVA: 0x000960C0 File Offset: 0x000942C0
		public void WoundTroop(CharacterObject troop, int numberToWound = 1, UniqueTroopDescriptor troopSeed = default(UniqueTroopDescriptor))
		{
			int index = this.FindIndexOfTroop(troop);
			this.AddToCountsAtIndex(index, 0, numberToWound, 0, true);
		}

		// Token: 0x06002355 RID: 9045 RVA: 0x000960E4 File Offset: 0x000942E4
		void ISerializableObject.SerializeTo(IWriter writer)
		{
			writer.WriteInt(this.Count);
			writer.WriteInt(this.VersionNo);
			if (this.data != null)
			{
				writer.WriteInt(this.data.Length);
				foreach (TroopRosterElement troopRosterElement in this.data)
				{
					writer.WriteSerializableObject(troopRosterElement);
				}
				return;
			}
			writer.WriteInt(0);
		}

		// Token: 0x06002356 RID: 9046 RVA: 0x00096150 File Offset: 0x00094350
		void ISerializableObject.DeserializeFrom(IReader reader)
		{
			this._count = reader.ReadInt();
			this.VersionNo = reader.ReadInt();
			int num = reader.ReadInt();
			this.data = new TroopRosterElement[num];
			for (int i = 0; i < num; i++)
			{
				this.data[i] = (TroopRosterElement)reader.ReadSerializableObject();
			}
		}

		// Token: 0x06002357 RID: 9047 RVA: 0x000961AC File Offset: 0x000943AC
		public int Sum(Func<TroopRosterElement, int> selector)
		{
			int num = 0;
			for (int i = 0; i < this._count; i++)
			{
				num += selector(this.data[i]);
			}
			return num;
		}

		// Token: 0x06002358 RID: 9048 RVA: 0x000961E2 File Offset: 0x000943E2
		public void OnHeroHealthStatusChanged(Hero hero)
		{
			this.UpdateVersion();
			this._totalWoundedHeroes += (hero.IsWounded ? 1 : -1);
			this.OnNumberChanged(false, true, false);
		}

		// Token: 0x06002359 RID: 9049 RVA: 0x0009620C File Offset: 0x0009440C
		internal void AddTroopTempXp(CharacterObject troop, int gainedXp)
		{
			int num = this.FindIndexOfTroop(troop);
			if (num >= 0)
			{
				TroopRosterElement[] array = this.data;
				int num2 = num;
				array[num2].DeltaXp = array[num2].DeltaXp + gainedXp;
			}
		}

		// Token: 0x0600235A RID: 9050 RVA: 0x00096240 File Offset: 0x00094440
		public void ClearTempXp()
		{
			for (int i = 0; i < this._count; i++)
			{
				this.data[i].DeltaXp = 0;
			}
		}

		// Token: 0x0600235B RID: 9051 RVA: 0x00096270 File Offset: 0x00094470
		public void UpdateVersion()
		{
			PartyBase ownerParty = this.OwnerParty;
			if (ownerParty != null)
			{
				MobileParty mobileParty = ownerParty.MobileParty;
				if (mobileParty != null)
				{
					mobileParty.UpdateVersionNo();
				}
			}
			int versionNo = this.VersionNo;
			this.VersionNo = versionNo + 1;
		}

		// Token: 0x0600235C RID: 9052 RVA: 0x000962AC File Offset: 0x000944AC
		public TroopRoster CloneRosterData()
		{
			TroopRoster troopRoster = new TroopRoster();
			if (this.data != null)
			{
				for (int i = 0; i < this.data.Length; i++)
				{
					TroopRosterElement troopRosterElement = this.data[i];
					if (troopRosterElement.Character != null)
					{
						troopRoster.AddToCounts(this.data[i].Character, troopRosterElement.Number, false, troopRosterElement.WoundedNumber, 0, true, -1);
					}
				}
			}
			return troopRoster;
		}

		// Token: 0x04000AB3 RID: 2739
		private static readonly List<TroopRoster> InstanceListForLoadGame = new List<TroopRoster>();

		// Token: 0x04000AB5 RID: 2741
		[SaveableField(0)]
		internal TroopRosterElement[] data;

		// Token: 0x04000AB6 RID: 2742
		[SaveableField(1)]
		internal int _count;

		// Token: 0x04000AB9 RID: 2745
		[CachedData]
		private int _totalRegulars;

		// Token: 0x04000ABA RID: 2746
		[CachedData]
		private int _totalWoundedRegulars;

		// Token: 0x04000ABB RID: 2747
		[CachedData]
		private int _totalWoundedHeroes;

		// Token: 0x04000ABC RID: 2748
		[CachedData]
		private int _totalHeroes;

		// Token: 0x04000ABD RID: 2749
		[SaveableField(8)]
		private bool _isPrisonRoster;

		// Token: 0x04000ABE RID: 2750
		[CachedData]
		private MBList<TroopRosterElement> _troopRosterElements;

		// Token: 0x04000ABF RID: 2751
		[CachedData]
		private int _troopRosterElementsVersion;

		// Token: 0x04000AC0 RID: 2752
		[CachedData]
		private bool _isInitialized;
	}
}
